package com.lzs.lzscodesandbox.utils;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.StrUtil;
import com.lzs.lzscodesandbox.model.ExecuteMessage;

import java.io.*;

/**
 * 进程工具类
 */
public class  ProcessUtils {
    /**
     * 执行进程并获取信息
     * @param runProcess
     * @return
     * @throws Exception
     */
    // 有正常和错误返回，所以返回值是两个，所以新建对象ExecuteMessage
    public static ExecuteMessage runProcessAndGetMessage(Process runProcess,String opName) throws Exception {
        ExecuteMessage executeMessage = new ExecuteMessage();

        // 计时器
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();// 开启

// 直到程序Process运行完成才拿到 错误码
        int exitValue = runProcess.waitFor();
        executeMessage.setExitValue(exitValue);
        if (exitValue == 0) {// 正常退出
            System.out.println(opName + "成功");
            // 拿到编译后的输出信息，程序会把命令执行后的输出写到输入流（InputStream）里，从输入流读取
            // 分批获取进程的正常输出
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));// InputStreamReader包装输入流,BufferedReader成批成块的读取
            StringBuilder compileOutputStringBuilder = new StringBuilder();
            // bufferedReader.readLine()每次读取一行，所以while逐行读取
            String compileOutputLine;
            while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    System.out.println(compileOutputLine);
                compileOutputStringBuilder.append(compileOutputLine);
            }
            executeMessage.setMessage(compileOutputStringBuilder.toString());
        } else {
            System.out.println(opName + "失败，错误码：" + exitValue);
            // 分批获取进程的正常输出
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));// InputStreamReader包装输入流,BufferedReader成批成块的读取
            StringBuilder compileOutputStringBuilder = new StringBuilder();
            // bufferedReader.readLine()每次读取一行，所以while逐行读取
            String compileOutputLine;
            while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    System.out.println(compileOutputLine);
                compileOutputStringBuilder.append(compileOutputLine);
            }
            // 分批获取进程的输出
            BufferedReader errorBufferedReader = new BufferedReader(new InputStreamReader(runProcess.getErrorStream()));// InputStreamReader包装输入流,BufferedReader成批成块的读取
            StringBuilder erroeCompileOutputStringBuilder = new StringBuilder();
            // bufferedReader.readLine()每次读取一行，所以while逐行读取
            String errorCompileOutputLine;
            while ((errorCompileOutputLine = errorBufferedReader.readLine()) != null) {
//                    System.out.println(errorCompileOutputLine);
                erroeCompileOutputStringBuilder.append(errorCompileOutputLine);
            }
            executeMessage.setErrorMessage(erroeCompileOutputStringBuilder.toString());
        }
        stopWatch.stop();// 停止程序
        long lastTaskTimeMillis = stopWatch.getLastTaskTimeMillis();// 得到执行时间
        executeMessage.setTime(lastTaskTimeMillis);
        return executeMessage;
    }

    /**
     * 执行交互式进程并获取信息
     * @param runProcess
     * @param args
     * @return
     * @throws Exception
     */
    public static ExecuteMessage runInteractProcessAndGetMessage(Process runProcess,String args) throws Exception {
        ExecuteMessage executeMessage = new ExecuteMessage();

        // 向控制台输入程序
        OutputStream outputStream = runProcess.getOutputStream();// 给终端写信息，就要得到输出流
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);// 拿到输出流对象
        String[] s = args.split(" ");
        String join = StrUtil.join("\n",s)+ "\n";// 两个空格
        outputStreamWriter.write(join);

        outputStreamWriter.write(args);// 相当于输入 1 2
        outputStreamWriter.flush();// 相当于输入了回车
        // 分批获取进程的正常输出
        InputStream inputStream = runProcess.getInputStream();// 输入流读取终端信息
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));// InputStreamReader包装输入流,BufferedReader成批成块的读取
        StringBuilder compileOutputStringBuilder = new StringBuilder();

        // bufferedReader.readLine()每次读取一行，所以while逐行读取
        String compileOutputLine;
        while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    System.out.println(compileOutputLine);
            compileOutputStringBuilder.append(compileOutputLine);
        }
        executeMessage.setMessage(compileOutputStringBuilder.toString());
        // 资源回收，否则会卡死
        outputStreamWriter.close();
        outputStream.close();
        inputStream.close();
        runProcess.destroy();

        return executeMessage;
    }
}
